#include "../edit/Lighter.h"
#include "unittest.h"

class CTestLighter : public CSyntaxLighter
{
public:
    void testClearBlocks() 
    {
        ClearBlocks();
    }
    int testAddBlock(Block* blk) 
    {
        return AddBlock(blk);
    }
    unsigned int testFindNextBlockStart(CharPos* pos, Block* blk) 
    {
        return FindNextBlockStart (pos, blk);
    }
    unsigned int testFindNextBlockCommentOff(CharPos* pos, Block* blk)
    {
        return FindNextBlockCommentOff (pos, blk);
    }
    unsigned int testMatchQuote(CharPos* pos, Block* blk)
    {
        return MatchQuote(pos, blk);
    }
    const char* testFindQuote(const char* str, char quote='\0')
    {
        return FindQuote(str, quote);
    }
    void testColorThisBlock(COLORREF* colorarray, size_t size, const Block* blk, CharPos* pos)
    {
        ColorThisBlock(colorarray, size, blk, pos);
    }
    void testColorUntilNextBlock (COLORREF* colorarray, size_t size, const Block* nextblk, CharPos* pos, const char* txt)
    {
        ColorUntilNextBlock (colorarray, size, nextblk, pos, txt);
    }
    int testAddBlock(const Block* blk)
    {
        return AddBlock(blk);
    }
};

TEST_GROUP (SyntaxLighter)
{
}

TEST_CASE (SyntaxLighter, test_CompareCharPosWithBlock)
{
    CharPos charpos;
    Block blk;

    blk.row1 = 5; blk.idx1 = 6; blk.row2 = 5; blk.idx2 = 8;
    charpos.row = 5; charpos.idx = 5;
    TEST_ASSERT (CompareCharPosWithBlock(&charpos, &blk) < 0);

    charpos.row = 4; charpos.idx = 10;
    TEST_ASSERT (CompareCharPosWithBlock(&charpos, &blk) < 0);
    
    charpos.row = 5; charpos.idx = 6;
    TEST_ASSERT (CompareCharPosWithBlock(&charpos, &blk) == 0);
    
    charpos.row = 5; charpos.idx = 7;
    TEST_ASSERT (CompareCharPosWithBlock(&charpos, &blk) == 0);
    
    charpos.row = 5; charpos.idx = 8;
    TEST_ASSERT (CompareCharPosWithBlock(&charpos, &blk) == 0);
    
    charpos.row = 5; charpos.idx = 9;
    TEST_ASSERT (CompareCharPosWithBlock(&charpos, &blk) > 0);
    
    charpos.row = 6; charpos.idx = 0;
    TEST_ASSERT (CompareCharPosWithBlock(&charpos, &blk) > 0);

    
    blk.row1 = 5; blk.idx1 = 6; blk.row2 = 7; blk.idx2 = 1;
    charpos.row = 4; charpos.idx = 10;
    TEST_ASSERT (CompareCharPosWithBlock(&charpos, &blk) < 0);
    
    charpos.row = 5; charpos.idx = 5;
    TEST_ASSERT (CompareCharPosWithBlock(&charpos, &blk) < 0);
    
    charpos.row = 5; charpos.idx = 6;
    TEST_ASSERT (CompareCharPosWithBlock(&charpos, &blk) == 0);

    charpos.row = 5; charpos.idx = 7;
    TEST_ASSERT (CompareCharPosWithBlock(&charpos, &blk) == 0);

    charpos.row = 5; charpos.idx = 100;
    TEST_ASSERT (CompareCharPosWithBlock(&charpos, &blk) == 0);

    charpos.row = 6; charpos.idx = 0;
    TEST_ASSERT (CompareCharPosWithBlock(&charpos, &blk) == 0);

    charpos.row = 6; charpos.idx = 100;
    TEST_ASSERT (CompareCharPosWithBlock(&charpos, &blk) == 0);

    charpos.row = 7; charpos.idx = 0;
    TEST_ASSERT (CompareCharPosWithBlock(&charpos, &blk) == 0);
    
    charpos.row = 7; charpos.idx = 1;
    TEST_ASSERT (CompareCharPosWithBlock(&charpos, &blk) == 0);

    charpos.row = 7; charpos.idx = 2;
    TEST_ASSERT (CompareCharPosWithBlock(&charpos, &blk) > 0);

    charpos.row = 8; charpos.idx = 0;
    TEST_ASSERT (CompareCharPosWithBlock(&charpos, &blk) > 0);
}

TEST_CASE (SyntaxLighter, test_SearchCharPosInStringPosArray)
{
    Block array[10];
    unsigned int i;
    for (i = 0; i < 10; i++) {
        array[i].row1 = i;
        array[i].idx1 = i+5;
        array[i].row2 = i;
        array[i].idx2 = i+10;
    }
    
    CharPos pos;
    bool instring;

    pos.row = 0; pos.idx = 0;
    TEST_ASSERT (SearchCharPosInBlockArray(array, 9, &pos, &instring) == 0);
    TEST_ASSERT (instring == false);
    
    for (i = 0; i < 9; i++) {
        pos.row = i;
        pos.idx = pos.row+10;
        TEST_ASSERT (SearchCharPosInBlockArray(array, 9, &pos, &instring) == i);
        TEST_ASSERT (instring == true);
        pos.idx = pos.row+11;
        TEST_ASSERT (SearchCharPosInBlockArray(array, 9, &pos, &instring) == i+1);
        TEST_ASSERT (instring == false);
    }
    pos.row = 10;
    TEST_ASSERT (SearchCharPosInBlockArray(array, 9, &pos, &instring) == 9);
    TEST_ASSERT (instring == false);


    pos.row = 0; pos.idx = 0;
    TEST_ASSERT (SearchCharPosInBlockArray(array, 10, &pos, &instring) == 0);
    TEST_ASSERT (instring == false);
    
    for (i = 0; i < 10; i++) {
        pos.row = i;
        pos.idx = pos.row+10;
        TEST_ASSERT (SearchCharPosInBlockArray(array, 10, &pos, &instring) == i);
        TEST_ASSERT (instring == true);
        pos.idx = pos.row+11;
        TEST_ASSERT (SearchCharPosInBlockArray(array, 10, &pos, &instring) == i+1);
        TEST_ASSERT (instring == false);
    }
    pos.row = 11;
    TEST_ASSERT (SearchCharPosInBlockArray(array, 10, &pos, &instring) == 10);
    TEST_ASSERT (instring == false);


}

TEST_CASE (SyntaxLighter, test_CSyntaxLighter_constructor)
{
    CSyntaxLighter sl;

    TEST_ASSERT (sl.m_nBlocks == 0);
    TEST_ASSERT (sl.GetBlocks());
}

TEST_CASE (SyntaxLighter, test_CSyntaxLighter_SetDocument) 
{
    CSyntaxLighter sl;
    CTextDoc doc;

    sl.m_nBlocks = 5;
    sl.SetDocument(&doc);

    TEST_ASSERT (sl.m_nBlocks == 0);
    TEST_ASSERT (sl.GetBlocks());
}

TEST_CASE (SyntaxLighter, test_CSyntaxLighter_AddBlock)
{
    CTestLighter sl;
    Block blk = {0,0, 0,2, COMMENT_BLOCK};
    unsigned int i ;
    for (i = 0; i < 50; i++) {
        blk.row1 = i;
        blk.row2 = i;
        sl.testAddBlock(&blk);
    }

    TEST_ASSERT (sl.m_nBlocks == 50);
    Block* p = sl.GetBlocks();
    TEST_ASSERT (p);
    for (i = 0; i < 50; i++) {
        TEST_ASSERT(p[i].row1 == i);
        TEST_ASSERT(p[i].row2 == i);
        TEST_ASSERT(p[i].idx1 == 0);
        TEST_ASSERT(p[i].idx2 == 2);
        TEST_ASSERT(p[i].type == COMMENT_BLOCK);
    }
}

TEST_CASE(SyntaxLighter, test_CSyntaxLighter_FindQuote)
{
    CTestLighter tl;
    CSyntaxConfig syn;
    
    syn.SetQuote("'\"");
    syn.SetEscape("\\");
    tl.SetSyntax(&syn);

    const char* str1 = "hello, I'm dudu";
    const char* found;

    found = tl.testFindQuote(str1);
    TEST_ASSERT (found == str1+8);

    const char* str2 = " \"hey, ' hey\"";
    found = tl.testFindQuote(str2);
    TEST_ASSERT (found == str2+1);

    const char* str3 = "\"hey, ' hey\"";
    found = tl.testFindQuote(str3);
    TEST_ASSERT (found == str3);
    found = tl.testFindQuote(str3, '\'');
    TEST_ASSERT (found == str3 + 6);

    const char* str4 = "hey,  hey";
    found = tl.testFindQuote(str4);
    TEST_ASSERT (found == NULL);

    const char* str5 = "\\\"hello\"";
    found = tl.testFindQuote(str5);
    TEST_ASSERT (found == str5+7);

    const char* str6 = "\\\'hello\"";
    found = tl.testFindQuote(str6);
    TEST_ASSERT (found == str6+7);
    found = tl.testFindQuote(str6, '\'');
    TEST_ASSERT (found == NULL);
    found = tl.testFindQuote(str6, '"');
    TEST_ASSERT (found == str6+7);

    const char* str7 = "";
    found = tl.testFindQuote(str7);
    TEST_ASSERT (found == NULL);
    found = tl.testFindQuote(str7, '\'');
    TEST_ASSERT (found == NULL);
    found = tl.testFindQuote(str7, '"');
    TEST_ASSERT (found == NULL);
}

TEST_CASE(SyntaxLighter, test_CSyntaxLighter_FindNextBlockStart)
{
    CTextDoc doc;
    CTestLighter tl;
    CSyntaxConfig syn;
    char buf[1024];
    
    syn.SetQuote("'\"");
    syn.SetEscape("\\");
    tl.SetDocument(&doc);
    tl.SetSyntax(&syn);

    strcpy (buf, "\"who are you?\" 'I am \ndudu.'\n \\\"Nice to meeting you\"");
    
    CharPos pos = {0,0};
    doc.InsertTextAt(0,0, buf);

    Block blk;
    TEST_ASSERT (tl.testFindNextBlockStart(&pos, &blk) == IN_STRING);
    TEST_ASSERT (blk.row1 == 0 && blk.idx1 == 0 ); 
    TEST_ASSERT (blk.type == STRING_BLOCK);
    TEST_ASSERT (pos.row == 0 && pos.idx == 1);
    TEST_ASSERT (blk.quote == '"');

    pos.row = 0; pos.idx = 1;
    TEST_ASSERT (tl.testFindNextBlockStart(&pos, &blk) == IN_STRING);
    TEST_ASSERT (blk.row1 == 0 && blk.idx1 == 13);
    TEST_ASSERT (blk.type == STRING_BLOCK);
    TEST_ASSERT (blk.quote == '"');
    TEST_ASSERT (pos.row == 0 && pos.idx == 14);

    pos.row = 0; pos.idx = 14;
    TEST_ASSERT (tl.testFindNextBlockStart(&pos, &blk) == IN_STRING);
    TEST_ASSERT (blk.row1 == 0 && blk.idx1 == 15);
    TEST_ASSERT (blk.type == STRING_BLOCK);
    TEST_ASSERT (blk.quote == '\'');
    TEST_ASSERT (pos.row == 0 && pos.idx == 16);

    pos.row = 0; pos.idx = 16;
    TEST_ASSERT (tl.testFindNextBlockStart(&pos, &blk) == NORMAL);
    TEST_ASSERT (pos.row == 1 && pos.idx == 0);

    pos.row = 0; pos.idx = 20;
    TEST_ASSERT (tl.testFindNextBlockStart(&pos, &blk) == NORMAL);
    TEST_ASSERT (pos.row == 1 && pos.idx == 0);

    pos.row = 1; pos.idx = 0;
    TEST_ASSERT (tl.testFindNextBlockStart(&pos, &blk) == IN_STRING);
    TEST_ASSERT (blk.row1 == 1 && blk.idx1 == 5);
    TEST_ASSERT (blk.type == STRING_BLOCK);
    TEST_ASSERT (blk.quote == '\'');
    TEST_ASSERT (pos.row == 2 && pos.idx == 0);

    pos.row = 2; pos.idx = 0;
    TEST_ASSERT (tl.testFindNextBlockStart(&pos, &blk) == IN_STRING);
    TEST_ASSERT (blk.row1 == 2 && blk.idx1 == 22);
    TEST_ASSERT (blk.type == STRING_BLOCK);
    TEST_ASSERT (blk.quote == '"');
    TEST_ASSERT (pos.row == 3 && pos.idx == 0);

    doc.RemoveText(0, 0, LAST_LINE, EOL);
    strcpy(buf, "/*\n * this is a test \"\n */\n\" Who are you?\" // Someone asks ' \"\n' I am Dudu. Nice to meet you.'");
    doc.InsertTextAt(0,0, buf);
    syn.SetLineComment("//");
    syn.SetBlockCommentOn("/*");
    syn.SetBlockCommentOff("*/");

    pos.row = 0; pos.idx = 0;
    TEST_ASSERT (tl.testFindNextBlockStart(&pos, &blk) == IN_BLOCK_COMMENT);
    TEST_ASSERT (blk.type == COMMENT_BLOCK);
    TEST_ASSERT (blk.row1 == 0 && blk.idx1  == 0);
    TEST_ASSERT (pos.row == 1 && pos.idx == 0);

    pos.row = 1; pos.idx = 0;
    TEST_ASSERT (tl.testFindNextBlockStart(&pos, &blk) == IN_STRING);
    TEST_ASSERT (blk.type == STRING_BLOCK);
    TEST_ASSERT (blk.row1 == 1 && blk.idx1  == 18);
    TEST_ASSERT (blk.quote == '"');
    TEST_ASSERT (pos.row == 2 && pos.idx == 0);

    pos.row = 2; pos.idx = 0;
    TEST_ASSERT (tl.testFindNextBlockStart(&pos, &blk) == NORMAL);
    TEST_ASSERT (pos.row == 3 && pos.idx == 0);

    pos.row = 3; pos.idx = 0;
    TEST_ASSERT (tl.testFindNextBlockStart(&pos, &blk) == IN_STRING);
    TEST_ASSERT (blk.type == STRING_BLOCK);
    TEST_ASSERT (blk.row1 == 3 && blk.idx1  == 0);
    TEST_ASSERT (blk.quote == '"');
    TEST_ASSERT (pos.row == 3 && pos.idx == 1);

    pos.row = 3; pos.idx = 1;
    TEST_ASSERT (tl.testFindNextBlockStart(&pos, &blk) == IN_STRING);
    TEST_ASSERT (blk.type == STRING_BLOCK);
    TEST_ASSERT (blk.row1 == 3 && blk.idx1  == 14);
    TEST_ASSERT (blk.quote == '"');
    TEST_ASSERT (pos.row == 3 && pos.idx == 15);

    pos.row = 3; pos.idx = 15;
    TEST_ASSERT (tl.testFindNextBlockStart(&pos, &blk) == NORMAL);
    TEST_ASSERT (blk.type == COMMENT_BLOCK);
    TEST_ASSERT (blk.row1 == 3 && blk.idx1  == 16);
    TEST_ASSERT (blk.row2 == 3 && blk.idx2  == EOL);
    TEST_ASSERT (tl.m_nBlocks == 1);
    Block* added = (tl.GetBlocks()) + 0;
    TEST_ASSERT (memcmp(added, &blk, sizeof(Block)) == 0);
    TEST_ASSERT (pos.row == 4 && pos.idx == 0);

    pos.row = 4; pos.idx = 0;
    TEST_ASSERT (tl.testFindNextBlockStart(&pos, &blk) == IN_STRING);
    TEST_ASSERT (blk.type == STRING_BLOCK);
    TEST_ASSERT (blk.row1 == 4 && blk.idx1  == 0);
    TEST_ASSERT (blk.quote == '\'');
    TEST_ASSERT (pos.row == 4 && pos.idx == 1);

    pos.row = 4; pos.idx = 1;
    TEST_ASSERT (tl.testFindNextBlockStart(&pos, &blk) == IN_STRING);
    TEST_ASSERT (blk.type == STRING_BLOCK);
    TEST_ASSERT (blk.row1 == 4 && blk.idx1  == 30);
    TEST_ASSERT (blk.quote == '\'');
    TEST_ASSERT (pos.row == 5 && pos.idx == 0);

}

TEST_CASE (SyntaxLighter, test_CSyntaxLighter_FindNextBlockCommentOff)
{
    CTextDoc doc;
    CTestLighter tl;
    CSyntaxConfig syn;
    char buf[1024];
    Block blk;
    CharPos pos;

    tl.SetDocument(&doc);
    tl.SetSyntax(&syn);
    syn.SetQuote("'\"");
    syn.SetEscape("\\");
    syn.SetLineComment("//");
    syn.SetBlockCommentOn("/*");
    syn.SetBlockCommentOff("*/");

    strcpy(buf, "/*\n * this is a test \"\n */\n */ \" Who are you?\" // Someone asks ' \"\n' I am Dudu. Nice to meet you.'");
    doc.InsertTextAt(0,0, buf);
    blk.type = COMMENT_BLOCK;
    blk.row1 = 0; blk.idx1 = 0;

    pos.row = 0; pos.idx = 1;
    TEST_ASSERT (tl.testFindNextBlockCommentOff(&pos, &blk) == IN_BLOCK_COMMENT);
    TEST_ASSERT (pos.row == 1 && pos.idx == 0);

    pos.row = 1; pos.idx = 0;
    TEST_ASSERT (tl.testFindNextBlockCommentOff(&pos, &blk) == IN_BLOCK_COMMENT);
    TEST_ASSERT (pos.row == 2 && pos.idx == 0);
    
    pos.row = 2; pos.idx = 0;
    TEST_ASSERT (tl.testFindNextBlockCommentOff(&pos, &blk) == NORMAL);
    TEST_ASSERT (pos.row == 3 && pos.idx ==0);
    TEST_ASSERT (blk.row1 == 0 && blk.idx1 == 0 && blk.row2 == 2 && blk.idx2 == 2);
    TEST_ASSERT (blk.type == COMMENT_BLOCK);
    TEST_ASSERT (tl.m_nBlocks == 1);
    Block* added = (tl.GetBlocks()) + 0;
    TEST_ASSERT (memcmp(added, &blk, sizeof(Block)) == 0);
    
    pos.row = 3; pos.idx = 0;
    TEST_ASSERT (tl.testFindNextBlockCommentOff(&pos, &blk) == NORMAL);
    TEST_ASSERT (pos.row == 3 && pos.idx ==3);
    TEST_ASSERT (blk.row1 == 0 && blk.idx1 == 0 && blk.row2 == 3 && blk.idx2 == 2);
    TEST_ASSERT (blk.type == COMMENT_BLOCK);
    TEST_ASSERT (tl.m_nBlocks == 2);
    added = (tl.GetBlocks()) + 1;
    TEST_ASSERT (memcmp(added, &blk, sizeof(Block)) == 0);
}


TEST_CASE (SyntaxLighter, test_CSyntaxLighter_MatchQuote)
{
    CTextDoc doc;
    CTestLighter tl;
    CSyntaxConfig syn;
    char buf[1024];
    Block blk;
    CharPos pos;

    tl.SetDocument(&doc);
    tl.SetSyntax(&syn);
    syn.SetQuote("'\"");
    syn.SetEscape("\\");
    syn.SetLineComment("//");
    syn.SetBlockCommentOn("/*");
    syn.SetBlockCommentOff("*/");

    strcpy(buf, "/*\n * this is a test \"\n */\n */ \" Who are you?\" // Someone asks ' \"\n' I am Dudu. Nice to meet you.'");
    doc.InsertTextAt(0,0, buf);
    blk.type = STRING_BLOCK;
    blk.row1 = 1; blk.idx1 = 18;
    blk.quote = '"';

    pos.row = 2; pos.idx = 0;
    TEST_ASSERT (tl.testMatchQuote(&pos, &blk) == IN_STRING);
    TEST_ASSERT (pos.row == 3 && pos.idx == 0);
    
    pos.row = 3; pos.idx = 0;
    TEST_ASSERT (tl.testMatchQuote(&pos, &blk) == NORMAL);
    TEST_ASSERT (pos.row == 3 && pos.idx ==5);
    TEST_ASSERT (blk.row1 == 1 && blk.idx1 == 18 && blk.row2 == 3 && blk.idx2 == 4);
    TEST_ASSERT (blk.type == STRING_BLOCK);
    TEST_ASSERT (blk.quote == '"');
    TEST_ASSERT (tl.m_nBlocks == 1);
    Block* added = (tl.GetBlocks()) + 0;
    TEST_ASSERT (memcmp(added, &blk, sizeof(Block)) == 0);
    
    pos.row = 3; pos.idx = 5;
    TEST_ASSERT (tl.testMatchQuote(&pos, &blk) == NORMAL);
    TEST_ASSERT (pos.row == 3 && pos.idx ==19);
    TEST_ASSERT (blk.row1 == 1 && blk.idx1 == 18 && blk.row2 == 3 && blk.idx2 == 18);
    TEST_ASSERT (blk.type == STRING_BLOCK);
    TEST_ASSERT (tl.m_nBlocks == 2);
    added = (tl.GetBlocks()) + 1;
    TEST_ASSERT (memcmp(added, &blk, sizeof(Block)) == 0);

    pos.row = 1; pos.idx = 0;
    TEST_ASSERT (tl.testMatchQuote(&pos, &blk) == NORMAL);
    TEST_ASSERT (pos.row == 2 && pos.idx ==0);
    TEST_ASSERT (blk.row1 == 1 && blk.idx1 == 18 && blk.row2 == 1 && blk.idx2 == 18);
    TEST_ASSERT (blk.type == STRING_BLOCK);
    TEST_ASSERT (tl.m_nBlocks == 3);
    added = (tl.GetBlocks()) + 2;
    TEST_ASSERT (memcmp(added, &blk, sizeof(Block)) == 0);

}

TEST_CASE(SyntaxLighter, test_CSyntaxLighter_FindAllBlocks)
{
    CTextDoc doc;
    CSyntaxLighter sl;
    CSyntaxConfig syn;

    sl.SetDocument(&doc);
    sl.SetSyntax(&syn);
    syn.SetQuote("'\"");
    syn.SetEscape("\\");
    syn.SetLineComment("//");
    syn.SetBlockCommentOn("/*");
    syn.SetBlockCommentOff("*/");

    doc.ReadFile("blocktest.txt");

    sl.FindAllBlocks();
    TEST_ASSERT (sl.m_nBlocks == 6);
    
    Block* blk_array = sl.GetBlocks();
    TEST_ASSERT (blk_array);

    Block blk0 = {0, 0, 3, 1, COMMENT_BLOCK, 0};
    TEST_ASSERT (memcmp (&(blk_array[0]), &blk0, sizeof(Block)) == 0);

    Block blk1 = {5, 9, 5, 18, STRING_BLOCK, '"'};
    TEST_ASSERT (memcmp (&(blk_array[1]), &blk1, sizeof(Block)) == 0);
    Block blk2 = {5, 21, 5, 24, STRING_BLOCK, '"'};
    TEST_ASSERT (memcmp (&(blk_array[2]), &blk2, sizeof(Block)) == 0);
    Block blk3 = {6, 0, 6, EOL, COMMENT_BLOCK, 0};
    TEST_ASSERT (memcmp (&(blk_array[3]), &blk3, sizeof(Block)) == 0);
    Block blk4 = {7, 0, 10, 1, COMMENT_BLOCK, 0};
    TEST_ASSERT (memcmp (&(blk_array[4]), &blk4, sizeof(Block)) == 0);
    Block blk5 = {11, 0, LAST_LINE, EOL, STRING_BLOCK, '\''};
    TEST_ASSERT (memcmp (&(blk_array[5]), &blk5, sizeof(Block)) == 0);

}

TEST_CASE (SyntaxLighter, test_ColorThisBlock)
{
    CTestLighter tl;
    COLORREF clr_ar[20];
    size_t ar_size = 20;
    Block blk;
    CharPos pos;
    int i;

    memset (clr_ar, 0, sizeof(clr_ar));
    pos.row = 2; pos.idx = 0;
    blk.row1 = 0; blk.idx1 = 100; blk.row2 = 3; blk.idx2 = 0;; blk.type =  COMMENT_BLOCK;
    tl.testColorThisBlock(clr_ar, 20, &blk, &pos);
    TEST_ASSERT (pos.row == 2 && pos.idx == 20);
    for (i = 0; i < 20; i++) {
        TEST_ASSERT (clr_ar[i] == DEFAULT_COMMENTCOLOR);
    }

    memset (clr_ar, 0, sizeof(clr_ar));
    pos.row = 2; pos.idx = 0;
    blk.row1 = 0; blk.idx1 = 100; blk.row2 = 3; blk.idx2 = 0;; blk.type =  STRING_BLOCK;
    tl.testColorThisBlock(clr_ar, 20, &blk, &pos);
    TEST_ASSERT (pos.row == 2 && pos.idx == 20);
    for (i = 0; i < 20; i++) {
        TEST_ASSERT (clr_ar[i] == DEFAULT_STRINGCOLOR);
    }

    memset (clr_ar, 0, sizeof(clr_ar));
    pos.row = 2; pos.idx = 0;
    blk.row1 = 0; blk.idx1 = 100; blk.row2 = 2; blk.idx2 = 0; blk.type =  STRING_BLOCK;
    tl.testColorThisBlock(clr_ar, 20, &blk, &pos);
    TEST_ASSERT (pos.row == 2 && pos.idx == 1);
    TEST_ASSERT (clr_ar[0] == DEFAULT_STRINGCOLOR);

    memset (clr_ar, 0, sizeof(clr_ar));
    pos.row = 2; pos.idx = 0;
    blk.row1 = 0; blk.idx1 = 100; blk.row2 = 2; blk.idx2 = 10; blk.type =  STRING_BLOCK;
    tl.testColorThisBlock(clr_ar, 20, &blk, &pos);
    TEST_ASSERT (pos.row == 2 && pos.idx == 11);
    for (i = 0; i < 10; i++) {
        TEST_ASSERT (clr_ar[i] == DEFAULT_STRINGCOLOR);
    }

    memset (clr_ar, 0, sizeof(clr_ar));
    pos.row = 2; pos.idx = 2;
    blk.row1 = 2; blk.idx1 = 2; blk.row2 = 2; blk.idx2 = 10; blk.type =  STRING_BLOCK;
    tl.testColorThisBlock(clr_ar, 20, &blk, &pos);
    TEST_ASSERT (pos.row == 2 && pos.idx == 11);
    for (i = 2; i < 10; i++) {
        TEST_ASSERT (clr_ar[i] == DEFAULT_STRINGCOLOR);
    }
}

TEST_CASE (SyntaxLighter, testColorUntilNextBlock)
{
    CSyntaxConfigArray arr;
    CTestLighter tl;
    COLORREF clr_ar[50];
    CharPos pos;
    int i;

    arr.ReadFromFile("syntax.hilight");
    CSyntaxConfig* syntax;
    int ret = arr.FindSyntaxByFileExtension("logo", &syntax);
    TEST_ASSERT (ret >= 0);
    tl.SetSyntax(syntax);

    char* txt = "  pencolor x,y,s*5 # hello";
    Block nextblock = {2, 19, 2, EOL, COMMENT_BLOCK, ' '};
    
    memset (clr_ar, 0, sizeof(clr_ar));
    pos.row = 2; pos.idx = 0;
    tl.testColorUntilNextBlock(clr_ar, 50, &nextblock, &pos, txt);
    TEST_ASSERT (pos.row == 2 && pos.idx == 19);
    for (i = 0; i < 2; i++) {
        TEST_ASSERT (clr_ar[i] == DEFAULT_NORMALCOLOR);
    }
    for (; i < 10; i++) {
        TEST_ASSERT (clr_ar[i] == DEFAULT_KEYWORDCOLOR);
    }
    for (; i < 19; i++) {
        TEST_ASSERT (clr_ar[i] == DEFAULT_NORMALCOLOR);
    }

    txt = "  pencolor x,y,s*5 penup # hello";
    nextblock.row1 = 2; nextblock.idx1 = 25; 
    nextblock.row2 = 2; nextblock.idx2 = EOL;
    nextblock.type = COMMENT_BLOCK; nextblock.quote = ' ';
    memset (clr_ar, 0, sizeof(clr_ar));
    pos.row = 2; pos.idx = 0;
    tl.testColorUntilNextBlock(clr_ar, 50, &nextblock, &pos, txt);
    TEST_ASSERT (pos.row == 2 && pos.idx == 25);
    for (i = 0; i < 2; i++) {
        TEST_ASSERT (clr_ar[i] == DEFAULT_NORMALCOLOR);
    }
    for (; i < 10; i++) {
        TEST_ASSERT (clr_ar[i] == DEFAULT_KEYWORDCOLOR);
    }
    for (; i < 19; i++) {
        TEST_ASSERT (clr_ar[i] == DEFAULT_NORMALCOLOR);
    }
    for (; i < 24; i++) {
        TEST_ASSERT (clr_ar[i] == DEFAULT_KEYWORDCOLOR);
    }
    for (; i < 25; i++) {
        TEST_ASSERT (clr_ar[i] == DEFAULT_NORMALCOLOR);
    }

    txt = "reset";
    pos.row = 2; pos.idx = 0;
    tl.testColorUntilNextBlock(clr_ar, 5, NULL, &pos, txt);
    TEST_ASSERT (pos.row == 2 && pos.idx == 5);
    for (i = 0; i < 5; i++) {
        printf ("i = %d\n", i);
        TEST_ASSERT (clr_ar[i] == DEFAULT_KEYWORDCOLOR);
    }


}

TEST_CASE (SyntaxLighter, testColorTheLine)
{
    CSyntaxConfigArray arr;
    CTestLighter tl;
    COLORREF* clr_ar = NULL;
    unsigned int i;

    arr.ReadFromFile("syntax.hilight");
    CSyntaxConfig* syntax;
    int ret = arr.FindSyntaxByFileExtension("logo", &syntax);
    TEST_ASSERT (ret >= 0);
    tl.SetSyntax(syntax);

    Block blk;
    blk.row1 = 1; blk.idx1 = 0; 
    blk.row2 = 2; blk.idx2 = 0;
    blk.type = COMMENT_BLOCK; blk.quote = ' ';
    tl.testAddBlock(&blk);

    blk.row1 = 2; blk.idx1 = 25;
    blk.row2 = 2; blk.idx2 = EOL;
    blk.type = COMMENT_BLOCK; blk.quote = ' ';
    tl.testAddBlock(&blk);

    char* txt = "  pencolor x,y,s*5 penup # hello penup";
    ret = tl.ColorTheLine(2, txt, &clr_ar);
    TEST_ASSERT ((unsigned int)ret == strlen(txt));
    TEST_ASSERT (clr_ar);
    
    TEST_ASSERT (clr_ar[0] == DEFAULT_COMMENTCOLOR);
    TEST_ASSERT (clr_ar[1] == DEFAULT_NORMALCOLOR);
    for (i = 2; i < 10; i++) {
        TEST_ASSERT (clr_ar[i] == DEFAULT_KEYWORDCOLOR);
    }
    for (; i < 19; i++) {
        TEST_ASSERT (clr_ar[i] == DEFAULT_NORMALCOLOR);
    }
    for (; i < 24; i++) {
        TEST_ASSERT (clr_ar[i] == DEFAULT_KEYWORDCOLOR);
    }
    for (; i < 25; i++) {
        TEST_ASSERT (clr_ar[i] == DEFAULT_NORMALCOLOR);
    }
    for (; i < strlen (txt); i ++) {
        TEST_ASSERT (clr_ar[i] == DEFAULT_COMMENTCOLOR);
    }
    free (clr_ar);

    tl.testClearBlocks();
    txt = "if x == 3 && y == 4";
    ret = tl.ColorTheLine(1, txt, &clr_ar);
    TEST_ASSERT (clr_ar);
    TEST_ASSERT((size_t) ret == strlen(txt));
    for (i = 0; i < 2; i++) {
        TEST_ASSERT (clr_ar[i] == DEFAULT_KEYWORDCOLOR);
    }
    for (i = 2 ; i < strlen(txt) ; i++) {
        TEST_ASSERT (clr_ar[i] == DEFAULT_NORMALCOLOR);
    }
}